const scoreEle = document.getElementById('score')
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const width = 50;
const height = 50;
const step = 10;
let direction = 'l'; // 方向: j: 下;k:上;h:左;l:右;
let mapArr = []; // 地图
let initX = Math.floor(width/2);
let initY = Math.floor(height/2)
let bodyArr = [{
  x: initX+3,
  y: initY,
},
{
  x: initX+2,
  y: initY,
},
{
  x: initX+1,
  y: initY,
},
{
  x: initX,
  y: initY,
}];
let defaultType = 0; // 0: 普通地形， 1: 障碍

let timeId = null;
let foodPosition = null; // 食物位置
const foodScore = 10;

let speed = 200

// 获取地图宽度，此处用函数返回是因为数组是引用类型的
const getWidthArr = (width) => {
  let widthArr = [];
  for(let i = 0; i < width; i++) {
    widthArr.push(defaultType)
  }
  return widthArr
}
// 生成地图二维数组
const getMapArr = (width, height) => {
  let mapArr = []
  for(let i = 0; i < height; i++) {
    mapArr.push(getWidthArr(width))
  }
  return mapArr
}
// 开始游戏
const gameStart = (speed) => {
  // 清除计时器，让游戏从头开始
  clearInterval(timeId);
  // 记录计时器id，后期清理计时器用
  timeId = setInterval(() => {
    mapArr = getMapArr(width, height)
    // 蛇的身体开始移动,
    bodyMove(bodyArr, direction)
    setBody(mapArr, bodyArr);
    drawMap(mapArr);
  }, speed);
}

const checkIsInBody = (bodyArr, position) => {
  let isInBody = false
  for(let index = 0; index < bodyArr.length - 1; index++) {
    if(bodyArr[index].x === position.x && bodyArr[index].y === position.y) {
      isInBody = true;
      return
    }
  }
  return isInBody
}
const foodRandom = (width, height) => {
  let foodX = Math.floor((Math.random() * width))
  let foodY = Math.floor((Math.random() * height))
  while (checkIsInBody(bodyArr, {x: foodX, y: foodY})) {
    if(foodX < width - 1) {
      foodX += 1;
    } else {
      foodX = 0
      if(foodY < height - 1) {
        foodY += 1
      } else {
        foodY = 0
      }
    }
  }
  
  return {
    x: foodX,
    y: foodY,
  }
}

const setBody = (mapArr,bodyArr) => {
  bodyArr.forEach(item => {
    mapArr[item.y][item.x] = 1;
  })
}
// 判定游戏是否结束
const isGameOver = (bodyArr, nextPos) => {
  let result = false;
  bodyArr.forEach(item => {
    if(item.x === nextPos.x && item.y === nextPos.y) {
      result = true
    }
  })
  return result
}
// 吃到食物
const eatFood = (nextPos, foodPosition) => {
  if(nextPos.x === foodPosition.x && nextPos.y === foodPosition.y) {
    return true
  } else {
    return false
  }
}

// 计算蛇身体的移动，并设置蛇身的数组
const bodyMove = (bodyArr, direction = 'k') => {
  let head = bodyArr[0]
  let nextPos = {};
  // 根据方向计算正常行走的下一个方格位置
  switch (direction) {
    case 'k':
      nextPos = {
        x: head.x,
        y: head.y - 1,
      }
      break;
    case 'j':
      nextPos = {
        x: head.x,
        y: head.y + 1,
      }
      break;
    case 'h':
      nextPos = {
        x: head.x - 1,
        y: head.y,
      }
      break;
    case 'l':
      nextPos = {
        x: head.x + 1,
        y: head.y,
      }
      break;
    default:
      nextPos = {
        x: head.x + 1,
        y: head.y,
      }
      break;
  }
  // 考虑穿越边界
  let nextPosY = nextPos.y;
  let nextPosX = nextPos.x;
  if(nextPosY < 0) {
    nextPos = {
      x: head.x,
      y: height - 1,
    }
  }
  if (nextPosY > mapArr.length - 1) {
    nextPos = {
      x: head.x,
      y: 0,
    }
  }
  if (nextPosX < 0) {
    nextPos = {
      x: width - 1,
      y: head.y,
    }
  }
  if (nextPosX > width - 1) {
    nextPos = {
      x: 0,
      y: head.y,
    }
  }
  // 判定游戏是否结束
  if(isGameOver(bodyArr, nextPos)) {
    alert('game over!')
    clearInterval(timeId);
  } else {
    // 判定是否吃到食物
    if(eatFood(nextPos, foodPosition)) {
      // 随机食物位置
      foodPosition = foodRandom(width, height)
      // 增加获得的分数
      scoreEle.innerHTML = +scoreEle.innerHTML + foodScore;
      // if(+scoreEle.innerHTML >= 30) {
      //   speed = 10
      //   gameStart(speed);
      // }
    } else {
      bodyArr.pop();
    }
    bodyArr.unshift(nextPos);
  }
}
// 绘制地图
const drawMap = (mapArr) => {
  ctx.fillStyle = "rgb(255,255,255)";
  ctx.clearRect(0, 0, width * step, height * step);
  ctx.fillStyle = "rgb(0,0,0)";
  ctx.strokeStyle = "rgb(0,0,0)";
  // 遍历二维数组，根据二维数组记录的类型绘制地图
  mapArr.forEach((yItem, yIndex) => {
    yItem.forEach((xItem, xIndex) => {
      if(xItem === defaultType) {
        ctx.fillStyle = "rgb(0,0,0)";
        ctx.fillRect(step * xIndex, step * yIndex, step, step)
        // ctx.strokeStyle = "rgb(0,0,0)";
        // ctx.strokeRect(step * xIndex, step * yIndex, step, step)
      } else {
        ctx.fillStyle = "rgb(255,255,255)";
        ctx.fillRect(step * xIndex, step * yIndex, step, step)
        // ctx.fillStyle = "rgb(255,0,0)";
        // ctx.fillRect(step * xIndex, step * yIndex, step, step)
      }
    })
  });
  // 绘制食物
  ctx.fillStyle = "rgb(255,0,0)";
  ctx.fillRect(step * foodPosition.x, step * foodPosition.y, step, step)
}

// 初始化食物位置
foodPosition = foodRandom(width, height)

// 监听按键并设置蛇的方向
document.onkeydown = (e) => {
  let key = e.keyCode
  let blackList = {
    'j': 'k',
    'k': 'j',
    'h': 'l',
    'l': 'h',
  }
  let keyCodeMap = {
    '38': 'k',
    '40': 'j',
    '37': 'h',
    '39': 'l',
  }
  if(blackList[keyCodeMap[key]] === direction) {
    console.log('>>>>非法的方向')
    return
  } else {
    direction = keyCodeMap[key] || direction
  }
}

// 开始游戏
gameStart(speed);